#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/devinfo.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/list.h>
#include <linux/printk.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/spinlock.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/of_device.h>
#include <linux/acpi.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <linux/usb.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/hid.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <video/display_timing.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/fb.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/videomode.h>
#include <linux/list.h>
#include <linux/input.h>
#include <linux/timer.h>

#include "core.h"
#include "pinmux.h"

// 根据datasheet提供的管脚的功能信息
struct vir_pinctrl_drv_soc_info {
	struct device *dev;
	const struct pinctrl_pin_desc *pins;
	unsigned int npins;
	unsigned int group_index;
	unsigned int flags;
	const char *gpr_compatible;
	struct mutex mutex;

	/* MUX_MODE shift and mask in case SHARE_MUX_CONF_REG */
	unsigned int mux_mask;
	u8 mux_shift;

	/* generic pinconf */
	bool generic_pinconf;
	const struct pinconf_generic_params *custom_params;
	unsigned int num_custom_params;
	unsigned int num_decodes;
	void (*fixup)(unsigned long *configs, unsigned int num_configs,
		      u32 *raw_config);

	int (*gpio_set_direction)(struct pinctrl_dev *pctldev,
				  struct pinctrl_gpio_range *range,
				  unsigned offset,
				  bool input);
};

struct vir_pinctrl_pinctrl_drv {
	struct device *dev;
	struct pinctrl_dev *pctl;
    struct vir_pinctrl_drv_soc_info *info; // 存放芯片的Pins信息
};

struct vir_pinctrl_pin {
	unsigned int pin;
	unsigned int mux_mode;
	u16 input_reg;
	unsigned int input_val;
	u32 config;
};


// #pin把pin转换为字符串
// VIR_PINCTRL_PAD_RESERVE0 --> PIN_VIR_PINCTRL_PAD_RESERVE0
// name必须要是const字符串 b = PIN_VIR_PINCTRL_PAD_RESERVE0
#define VIR_PINCTRL_PIN(a, b) { .number = a, .name = #b }
#define VIR_PINCTRL_DRV_TO_PIN(vpin) VIR_PINCTRL_PIN(vpin, PIN_##vpin)

// 显示的是enum的字符串
enum vir_pinctrl_pads {
    VIR_PINCTRL_PAD_PIN_0 = 0,
	VIR_PINCTRL_PAD_PIN_1 = 1,
	VIR_PINCTRL_PAD_PIN_2 = 2,
	VIR_PINCTRL_PAD_PIN_3 = 3,
};

static const struct pinctrl_pin_desc vir_pinctrl_drv_pads[] = {
    VIR_PINCTRL_DRV_TO_PIN(VIR_PINCTRL_PAD_PIN_0),
    VIR_PINCTRL_DRV_TO_PIN(VIR_PINCTRL_PAD_PIN_1),
    VIR_PINCTRL_DRV_TO_PIN(VIR_PINCTRL_PAD_PIN_2),
    VIR_PINCTRL_DRV_TO_PIN(VIR_PINCTRL_PAD_PIN_3),
};

static struct vir_pinctrl_drv_soc_info vir_pinctrl_info = {
	.pins = vir_pinctrl_drv_pads,
	.npins = ARRAY_SIZE(vir_pinctrl_drv_pads),
};

static void vir_pinctrl_drv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset)
{
    dev_err(NULL, "vir_pinctrl_drv_pin_dbg_show %s\n", dev_name(pctldev->dev));
}

static struct group_desc *vir_pinctrl_pinctrl_find_group_by_name(
				struct pinctrl_dev *pctldev,
				const char *name)
{
	struct group_desc *grp = NULL;
	int i;

	for (i = 0; i < pctldev->num_groups; i++) {
		grp = pinctrl_generic_get_group(pctldev, i);
		if (grp && !strcmp(grp->name, name))
			break;
	}

	return grp;
}

static const char *vir_pinctrl_pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
{
	const struct pin_desc *desc;

	desc = pin_desc_get(pctldev, pin);
	if (!desc) {
		dev_err(pctldev->dev, "failed to get pin(%d) name\n",
			pin);
		return NULL;
	}

	return desc->name;
}

/*
 v_i2c {
     i2cgrp1: i2cgrp1 {
         functions = "pin0", "pin2";
         groups = <VIR_PINCTRL_PAD_PIN_0>, <VIR_PINCTRL_PAD_PIN_2>; // 需要和驱动中的pin的index相对应
         configs = <0x11223344 0x55667788>;
     };

     i2cgrp2: i2cgrp2 {
         functions = "pin1", "pin2";
         groups = <VIR_PINCTRL_PAD_PIN_1>, <VIR_PINCTRL_PAD_PIN_2>;
         configs = <0x11223344 0x55667788>;
     };
 };


 one pin ==> two pinctrl_map (one for mux, one for config)
 */
static int vir_pinctrl_drv_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, unsigned *num_maps)
{
    struct vir_pinctrl_pinctrl_drv *ipctl = pinctrl_dev_get_drvdata(pctldev);
    struct vir_pinctrl_drv_soc_info *info = ipctl->info;
    const struct group_desc *grp;
	struct pinctrl_map *new_map;
	struct device_node *parent;
    struct vir_pinctrl_pin *pin;
	int map_num = 1;
	int i, j;

    dev_err(NULL, "vir_pinctrl_drv_dt_node_to_map\n");

    dev_err(NULL, "np->name %s\n", np->name);

    grp = vir_pinctrl_pinctrl_find_group_by_name(pctldev, np->name);
    if (!grp) {
		dev_err(info->dev, "unable to find group for node %s\n",
			np->name);
		return -EINVAL;
	}

    dev_err(NULL, "grp->num_pins %d\n", grp->num_pins);

    for (i = 0; i < grp->num_pins; i++) {
		pin = &((struct vir_pinctrl_pin *)(grp->data))[i];
        /* 确定引脚配置的个数 */
		map_num++;
	}

    new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
	if (!new_map)
		return -ENOMEM;
    
    *map = new_map;
	*num_maps = map_num;

    /* create mux map */
    parent = of_get_parent(np);
	if (!parent) {
		kfree(new_map);
		return -EINVAL;
	}
	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
	new_map[0].data.mux.function = parent->name;
	new_map[0].data.mux.group = np->name;
    dev_err(NULL, "data.mux.function %s data.mux.group %s\n", parent->name, np->name);
    
	of_node_put(parent);

    /* 一个pin对应着一个mux和多个configs */

    /* create config map */
	new_map++;
	for (i = j = 0; i < grp->num_pins; i++) {
		struct vir_pinctrl_pin *pin = &((struct vir_pinctrl_pin *)(grp->data))[i];
        
		new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
		new_map[j].data.configs.group_or_pin =
				vir_pinctrl_pin_get_name(pctldev, pin->pin);
        dev_err(NULL, "pin->pin %d | new_map[j].data.configs.group_or_pin name %s\n", pin->pin, new_map[j].data.configs.group_or_pin);
		new_map[j].data.configs.configs = (unsigned long *)&pin->config;
		new_map[j].data.configs.num_configs = 1;
		j++;
	}
    
    return 0;
}

static void vir_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps)
{
	kfree(map);
}

static int vir_pinctrl_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, unsigned group)
{   
    struct vir_pinctrl_pinctrl_drv *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	unsigned int npins, pin_id;
	int i;
	struct group_desc *grp = NULL;
	struct function_desc *func = NULL;
    struct vir_pinctrl_pin *pin = NULL;

    dev_err(NULL, "vir_pinctrl_pmx_set\n");

    /*
	 * Configure the mux mode for each pin in the group for a specific
	 * function.
	 */
    
    grp = pinctrl_generic_get_group(pctldev, group);
	if (!grp)
		return -EINVAL;
    
    func = pinmux_generic_get_function(pctldev, selector);
	if (!func)
		return -EINVAL;

    npins = grp->num_pins;

    dev_err(NULL, "enable function %s group %s\n", func->name, grp->name);

    for (i = 0; i < npins; i++) {
        pin = &((struct vir_pinctrl_pin *)(grp->data))[i];
        pin_id = pin->pin;
        dev_err(NULL, "pin_id %d / name %s\n", pin_id, vir_pinctrl_pin_get_name(pctldev, pin_id));

        /* 真实的硬件设置寄存器 */
    }

    return 0;
}

static int vir_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset)
{
    dev_err(NULL, "set and enable pin %s as GPIO\n", pctldev->desc->pins[offset].name);
    return 0;
}

static int vir_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin_id, unsigned long *config)
{
    struct vir_pinctrl_pinctrl_drv *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;

    dev_err(NULL, "vir_pinctrl_pinconf_get pin_id %d\n", pin_id);
    
    return 0;
}

static int vir_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin_id, unsigned long *configs, unsigned num_configs)
{
    struct vir_pinctrl_pinctrl_drv *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
    int i = 0;

    dev_err(NULL, "vir_pinctrl_pinconf_set \n");
    dev_err(NULL, "pinconf set pin %s | num_configs %d | val %ld\n", info->pins[pin_id].name, num_configs, *configs);

    for (i = 0; i < num_configs; i++) {
        /* 硬件设置configs */
        /* configs的值来自于vir_pinctrl_drv_dt_node_to_map的设置 */
    }
    
    return 0;
}

static void vir_pinctrl_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin_id)
{
#if 0
    struct vir_pinctrl_pinctrl_drv *ipctl = pinctrl_dev_get_drvdata(pctldev);
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	unsigned long config;

    config = readl(ipctl->base + pin_reg->conf_reg);
#endif 

    // 读取硬件的config
    dev_err(NULL, "vir_pinctrl_pinconf_dbg_show \n");
}

static void vir_pinctrl_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned group)
{
    struct group_desc *grp;
	unsigned long config = 0;
	const char *name;
	int i, ret;

    dev_err(NULL, "vir_pinctrl_pinconf_group_dbg_show \n");

	if (group > pctldev->num_groups)
		return;

	grp = pinctrl_generic_get_group(pctldev, group);
	if (!grp)
		return;

	for (i = 0; i < grp->num_pins; i++) {
		struct vir_pinctrl_pin *pin = &((struct vir_pinctrl_pin *)(grp->data))[i];

		name = vir_pinctrl_pin_get_name(pctldev, pin->pin);
        /* 读取硬件的config */
//		ret = imx_pinconf_get(pctldev, pin->pin, &config);
//		if (ret)
//			return;
        dev_err(NULL, "  %s: 0x%lx\n", name, config);
	}
}

static int virtual_get_groups_count(struct pinctrl_dev *pctldev)
{
	return pctldev->desc->npins;
}

static const char *virtual_get_group_name(struct pinctrl_dev *pctldev,
				       unsigned selector)
{
	return pctldev->desc->pins[selector].name;
}

static int virtual_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
				  const unsigned **pins,
				  unsigned *npins)
{
   if (selector >= pctldev->desc->npins)
	   return -EINVAL;

   *pins = &pctldev->desc->pins[selector].number; // 应该返回一个pins的数组才行
   *npins = 1;

   return 0;
}

static const struct pinctrl_ops vir_pctrl_drv_ops = {
	.get_groups_count = pinctrl_generic_get_group_count,
	.get_group_name = pinctrl_generic_get_group_name,
	.get_group_pins = pinctrl_generic_get_group_pins,
//	.get_groups_count = virtual_get_groups_count,
//	.get_group_name = virtual_get_group_name,
//	.get_group_pins = virtual_get_group_pins,
	.pin_dbg_show = vir_pinctrl_drv_pin_dbg_show,
	.dt_node_to_map = vir_pinctrl_drv_dt_node_to_map,
	.dt_free_map = vir_pinctrl_dt_free_map,
};

struct pinmux_ops vir_pmx_drv_ops = {
	.get_functions_count = pinmux_generic_get_function_count,
	.get_function_name = pinmux_generic_get_function_name,
	.get_function_groups = pinmux_generic_get_function_groups,
	.set_mux = vir_pinctrl_pmx_set,
	.gpio_request_enable = vir_pinctrl_gpio_request_enable,
};

static const struct pinconf_ops vir_pinconf_drv_ops = {
	.pin_config_get = vir_pinctrl_pinconf_get,
	.pin_config_set = vir_pinctrl_pinconf_set,
	.pin_config_dbg_show = vir_pinctrl_pinconf_dbg_show,
	.pin_config_group_dbg_show = vir_pinctrl_pinconf_group_dbg_show,
};

static void vir_pinctrl_free_resources(struct vir_pinctrl_pinctrl_drv *ipctl)
{
	if (ipctl->pctl) {
        pinctrl_unregister(ipctl->pctl);
    }
}

static u32 vir_pinctrl_pinconf_parse_generic_config(struct device_node *np,
					    struct vir_pinctrl_pinctrl_drv *ipctl)
{
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	struct pinctrl_dev *pctl = ipctl->pctl;
	unsigned int num_configs;
	unsigned long *configs;
	int ret;

	if (!info->generic_pinconf)
		return 0;

//	ret = pinconf_generic_parse_dt_config(np, pctl, &configs, &num_configs);

    dev_err(NULL, "pinconf_generic_parse_dt_config ret %d\n", ret);
    
	if (ret) {
        return 0;
    }

    return 0;
}


static int vir_pinctrl_pinctrl_parse_groups(struct device_node *np,
    struct group_desc *grp,
    struct vir_pinctrl_pinctrl_drv *ipctl,
    u32 index)
{
    struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	int pin_size = 0;
    u32 val;
	int i = 0;
	u32 config = 0;
    struct vir_pinctrl_pin *pin = NULL;

    dev_err(NULL, "group(%d): %s\n", index, np->name);

    //config = vir_pinctrl_pinconf_parse_generic_config(np, ipctl);

    /* 确定pin group中的个数 */
    while(1) {
        if (of_property_read_u32_index(np, "groups", pin_size, &val) == 0) {
            pin_size++;
            dev_err(NULL, "PIN VAL %d\n", val);
        } else {
            break;
        }
    }
    
	/* Initialise group */
	grp->name = np->name;
    grp->num_pins = pin_size;
    grp->data = devm_kzalloc(info->dev, grp->num_pins * sizeof(struct vir_pinctrl_pin), GFP_KERNEL);
    grp->pins = devm_kzalloc(info->dev, grp->num_pins *sizeof(unsigned int), GFP_KERNEL);

    if (!grp->pins || !grp->data)
		return -ENOMEM;

    for (i = 0; i < grp->num_pins; i++) {
        pin = &((struct vir_pinctrl_pin *)(grp->data))[i];
        /* 设备树中的groups的参数需要和pinctrl_pin_desc的数组顺序需要相互对应才能找到对应的PIN */
        if (of_property_read_u32_index(np, "groups", i, &val) == 0) {
            grp->pins[i] = val;
            pin->pin = val;
        } else {
            grp->pins[i] = 0;
            pin->pin = 0;
        }

        /* get pin/function/config */
        /* 存储pin的config */
        of_property_read_u32_index(np, "configs", i, &pin->config);
    }

//    info->group_pins_index++;

	return 0;
}


static int vir_pinctrl_pinctrl_parse_functions(struct device_node *np,
    struct vir_pinctrl_pinctrl_drv *ipctl,
	u32 index)
{
    struct pinctrl_dev *pctl = ipctl->pctl;
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	struct device_node *child;
	struct function_desc *func;
	struct group_desc *grp;
	u32 i = 0;

    /* 解析v_i2c和v_i2s类似的function的参数 */
    dev_err(NULL, "parse function(%d): %s\n", index, np->name);

    func = pinmux_generic_get_function(pctl, index);
	if (!func)
		return -EINVAL;
    
    /* Initialise function */
    /* 设置v_i2c和v_i2s类似的function的参数 */
	func->name = np->name;
	func->num_group_names = of_get_child_count(np);
	if (func->num_group_names == 0) {
		dev_err(info->dev, "no groups defined in %pOF\n", np);
		return -EINVAL;
	}

    /* 解析v_i2c和v_i2s中的类似的i2cgrp1或i2cgrp2的group */
	func->group_names = devm_kcalloc(info->dev, func->num_group_names,
					 sizeof(char *), GFP_KERNEL);
	if (!func->group_names)
		return -ENOMEM;

	for_each_child_of_node(np, child) {
		func->group_names[i] = child->name;

        dev_err(NULL, "child id: %d, child->name %s\n", i, child->name);

		grp = devm_kzalloc(info->dev, sizeof(struct group_desc),
				   GFP_KERNEL);
		if (!grp)
            return -ENOMEM;

        dev_err(NULL, "info->group_index %d\n", info->group_index);
        
		mutex_lock(&info->mutex);
		radix_tree_insert(&pctl->pin_group_tree,
				  info->group_index++, grp);
		mutex_unlock(&info->mutex);

        /* 解析i2cgrp1或i2cgrp2类似的group */
		vir_pinctrl_pinctrl_parse_groups(child, grp, ipctl, i++);
	}
    

	return 0;
}

#if 0
    /* 虚拟的pinctrl controler */
    virtual_pincontroller {
        compatible = "jz2440,virtual_pinctrl";
        v_i2c {
            i2cgrp1: i2cgrp1 {
                functions = "i2c", "i2c";
                groups = "pin0", "pin1";
                configs = <0x11223344 0x55667788>;
            };

            i2cgrp2: i2cgrp2 {
                functions = "i2c", "i2c";
                groups = "pin2", "pin3";
                configs = <0x11223344 0x55667788>;
            };
        };

        v_i2s {
            i2sgrp1: i2sgrp1 {
                functions = "i2s", "i2s";
                groups = "pin2", "pin3";
                configs = <0x11223344 0x55667788>;
            };
            i2sgrp2: i2sgrp2 {
                functions = "i2s", "i2s";
                groups = "pin1", "pin2";
                configs = <0x11223344 0x55667788>;
            };
        };
    };

    virtual_i2c {
        compatible = "jz2440,virtual_i2c";
        pinctrl-names = "default";
        pinctrl-0 = <&i2cgrp1>;
    };

#endif

static int vir_pinctrl_pinctrl_probe_dt(struct platform_device *pdev,
    struct vir_pinctrl_pinctrl_drv *ipctl)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *child;
	struct pinctrl_dev *pctl = ipctl->pctl;
	struct vir_pinctrl_drv_soc_info *info = ipctl->info;
	u32 nfuncs = 0;
	u32 i = 0;

	if (!np)
		return -ENODEV;

    dev_err(NULL, "np name: %s\n", np->name);

    /* 获取np大节点个数,类似于v_i2c和v_i2s */
    nfuncs = of_get_child_count(np);
	if (nfuncs <= 0) {
		dev_err(&pdev->dev, "no functions defined\n");
		return -EINVAL;
	}

    /* 创建function存储v_i2c和v_i2s */
	for (i = 0; i < nfuncs; i++) {
		struct function_desc *function;

		function = devm_kzalloc(&pdev->dev, sizeof(*function), GFP_KERNEL);
		if (!function)
			return -ENOMEM;

		mutex_lock(&info->mutex);

        dev_err(NULL, "pin_function_tree index %d\n", i);
        
		radix_tree_insert(&pctl->pin_function_tree, i, function);
		mutex_unlock(&info->mutex);
	}
	pctl->num_functions = nfuncs;

    dev_err(NULL, "pctl->num_functions %d\n", nfuncs);

	info->group_index = 0;

    /* 获取v_i2c和v_i2s类似function节点下的groups的个数 */
	pctl->num_groups = 0;
	for_each_child_of_node(np, child) {
        pctl->num_groups += of_get_child_count(child);
    }
		
    dev_err(NULL, "pctl->num_groups %d\n", pctl->num_groups);
    
    /* 解析v_i2c和v_i2s类似的functions */
	i = 0;
	for_each_child_of_node(np, child) {
        vir_pinctrl_pinctrl_parse_functions(child, ipctl, i++);
    }
    
	return 0;
}

static int jz_pinctrl_probe(struct platform_device *pdev)
{
	struct device_node *np = NULL;
    struct device *dev = &pdev->dev;
	struct pinctrl_desc *vir_pinctrl_drv_desc;
    struct vir_pinctrl_pinctrl_drv *ipctl;
    
	int ret = 0;

    np = dev->of_node;
    if (!np) {
        dev_err(dev, "could not find device info\n");
        return -EINVAL;
    }

    /* 申请空间存放信息和PINS信息 */
    ipctl = devm_kzalloc(dev, sizeof(struct vir_pinctrl_pinctrl_drv), GFP_KERNEL);
    if (!ipctl)
        return -ENOMEM;

    /* 申请pinctrl_desc */
    vir_pinctrl_drv_desc = devm_kzalloc(dev, sizeof(struct pinctrl_desc), GFP_KERNEL);
    if (!vir_pinctrl_drv_desc) {
        return -ENOMEM;
    }

    /* 设置pinctrl_desc */
    vir_pinctrl_drv_desc->name = dev_name(dev);
    /* 设置datasheet中管脚的功能 */
    vir_pinctrl_drv_desc->pins = vir_pinctrl_info.pins;
    /* 设置datasheet中管脚的个数 */
    vir_pinctrl_drv_desc->npins = vir_pinctrl_info.npins;
    /* 处理设备树中pin controller中的某个节点:dt_node_to_map,把device_node转换为一系列的pinctrl_map */
    vir_pinctrl_drv_desc->pctlops = &vir_pctrl_drv_ops;
    /* 设置Pin引脚复用相关的函数 */
	vir_pinctrl_drv_desc->pmxops = &vir_pmx_drv_ops;
    /* 设置Pin引脚配置相关功能的函数 */
	vir_pinctrl_drv_desc->confops = &vir_pinconf_drv_ops;
	vir_pinctrl_drv_desc->owner = THIS_MODULE;

    /* platform specific callback */
    vir_pmx_drv_ops.gpio_set_direction = vir_pinctrl_info.gpio_set_direction;

    mutex_init(&vir_pinctrl_info.mutex);

    ipctl->info = &vir_pinctrl_info;
    vir_pinctrl_info.dev = dev;
    ipctl->dev = vir_pinctrl_info.dev;
    platform_set_drvdata(pdev, ipctl);  // 保存私有数据
    
    ret = devm_pinctrl_register_and_init(dev, vir_pinctrl_drv_desc, ipctl, &ipctl->pctl);
    if (ret) {
		dev_err(&pdev->dev, "could not register vir_pinctrl_drv_desc pinctrl driver\n");
		goto free;
	}

    // 解析controler设备树
    ret = vir_pinctrl_pinctrl_probe_dt(pdev, ipctl);
	if (ret) {
		dev_err(&pdev->dev, "fail to probe dt properties\n");
		goto free;
	}

    return pinctrl_enable(ipctl->pctl);

free:
    vir_pinctrl_free_resources(ipctl);
    return ret;
}

static int jz_pinctrl_remove(struct platform_device *pdev)
{	
	return 0;
}

static const struct of_device_id vir_pinctrl_drv[] = {
    { .compatible = "jz2440,virtual_pinctrl", },
    {},
};
MODULE_DEVICE_TABLE(of, vir_pinctrl_drv);

static struct platform_driver vir_pinctrl_driver = {
    .probe = jz_pinctrl_probe,
    .remove = jz_pinctrl_remove,
    .driver = {
        .name = "jz2440-vir-pinctrl-dev",
        .of_match_table = of_match_ptr(vir_pinctrl_drv),
    }
};

/*
 * init入口函数
*/
static int vir_pinctrl_drv_init(void)
{
    int ret = platform_driver_register(&vir_pinctrl_driver);
    if (ret < 0) {
        dev_err(NULL, "input_dev_init failed\n");
        return -EBUSY;
    }
    
    return ret;
}

/*
 * exit出口函数
 */
static void vir_pinctrl_drv_exit(void)
{
    platform_driver_unregister(&vir_pinctrl_driver);
    return;
}

module_init(vir_pinctrl_drv_init);
module_exit(vir_pinctrl_drv_exit);

MODULE_AUTHOR("huang");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("platform pinctrl drv");

